home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / HENSA / MATHS / PLPLOT / PLPLOT.ZIP / utils / plrender.c next >
Encoding:
C/C++ Source or Header  |  1994-08-25  |  41.8 KB  |  1,810 lines

  1. /* $Id: plrender.c,v 1.41 1994/08/25 04:05:36 mjl Exp $
  2.  * $Log: plrender.c,v $
  3.  * Revision 1.41  1994/08/25  04:05:36  mjl
  4.  * Eliminated unnecessary header file inclusion.
  5.  *
  6.  * Revision 1.40  1994/07/12  19:22:49  mjl
  7.  * Small change to ensure that cmap0 palette "sticks" when plot is saved from
  8.  * Tk driver.
  9.  *
  10.  * Revision 1.39  1994/06/30  18:55:48  mjl
  11.  * Minor changes to eliminate gcc -Wall warnings.
  12. */
  13.  
  14. /*
  15.     plrender.c
  16.  
  17.     Copyright 1991, 1992, 1993
  18.     Geoffrey Furnish
  19.     Maurice LeBrun
  20.  
  21.     This software may be freely copied, modified and redistributed without
  22.     fee provided that this copyright notice is preserved intact on all
  23.     copies and modified copies.
  24.  
  25.     There is no warranty or other guarantee of fitness of this software.
  26.     It is provided solely "as is". The author(s) disclaim(s) all
  27.     responsibility and liability with respect to this software's usage or
  28.     its effect upon hardware or computer systems.
  29.  
  30. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  31.  
  32.     This file contains the code to render a PLPLOT metafile, written by
  33.     the metafile driver, plmeta.c.
  34. */
  35.  
  36. char ident[] = "@(#) $Id: plrender.c,v 1.41 1994/08/25 04:05:36 mjl Exp $";
  37.  
  38. #include "plplotP.h"
  39. #include "plevent.h"
  40. #include "metadefs.h"
  41. #include <ctype.h>
  42.  
  43. static char *program_name = "plrender";
  44.  
  45. /* Static function prototypes. */
  46. /* INDENT OFF */
  47. /* These handle the command loop */
  48.  
  49. static void    process_next    (U_CHAR c);
  50. static void    plr_init    (U_CHAR c);
  51. static void    plr_line    (U_CHAR c);
  52. static void    plr_eop     (U_CHAR c);
  53. static void    plr_bop     (U_CHAR c);
  54. static void    plr_state    (U_CHAR c);
  55. static void    plr_esc        (U_CHAR c);
  56. static void    plresc_fill    (void);
  57. static void    plresc_rgb    (void);
  58. static void    plresc_ancol    (void);
  59.  
  60. /* Support functions */
  61.  
  62. static U_CHAR    getcommand    (void);
  63. static void    ungetcommand    (U_CHAR);
  64. static void    get_ncoords    (PLFLT *x, PLFLT *y, PLINT n);
  65. static void    NextFamilyFile    (U_CHAR *);
  66. static void    ReadPageHeader    (void);
  67. static void    plr_KeyEH    (PLKey *, void *, int *);
  68. static void    SeekToDisp    (long);
  69. static void    SeekOnePage    (void);
  70. static void    SeekToNextPage    (void);
  71. static void    SeekToCurPage    (void);
  72. static void    SeekToPrevPage    (void);
  73. static void    SeekTo        (FPOS_T);
  74. static void    doseek        (FPOS_T);
  75. static void    PageIncr    (void);
  76. static void    PageDecr    (void);
  77.  
  78. /* Initialization functions */
  79.  
  80. static void    Init        (int, char **);
  81. static void    OpenMetaFile    (int *, char **);
  82. static int    ReadFileHeader    (void);
  83. static void    Help        (void);
  84. static void     Usage        (char *);
  85. static void    myHelp        (void);
  86. static void    mySyntax    (void);
  87. static void    myNotes        (void);
  88.  
  89. /* Option handlers */
  90.  
  91. static int Opt_h    (char *, char *, void *);
  92. static int Opt_v    (char *, char *, void *);
  93. static int Opt_i    (char *, char *, void *);
  94. static int Opt_b    (char *, char *, void *);
  95. static int Opt_e    (char *, char *, void *);
  96. static int Opt_p    (char *, char *, void *);
  97.  
  98. /* Global variables */
  99. /* Mode flags for argument parsing */
  100.  
  101. static int mode_plrender = PL_PARSE_OVERRIDE;
  102. static int mode_plplot = 0;
  103. static int mode_showall = 0;
  104.  
  105. /* Page info */
  106.  
  107. static PLINT    disp_beg=1;    /* Where to start plotting */
  108. static PLINT    disp_end=-1;    /* Where to stop (0 to disable) */
  109. static PLINT    curdisp;    /* Current page number */
  110. static PLINT    cursub;        /* Current subpage */
  111. static PLINT    curpage;    /* Current plot number */
  112. static PLINT    nsubx;        /* subpages in x */
  113. static PLINT    nsuby;        /* subpages in y */
  114. static PLINT    target_disp;    /* Page we are seeking to */
  115. static PLINT    target_page;    /* Plot we are seeking to */
  116. static PLINT    delta;        /* Number of pages to go forward/back */
  117. static PLINT    pages;        /* Number of pages in file */
  118.  
  119. static int    no_pagelinks;    /* Set if metafile doesn't have page links */
  120. static int    end_of_page;    /* Set when we're at the end of a page */
  121. static int    seek_mode;    /* Set after a seek, before a BOP */
  122. static int    addeof_beg;    /* Set when we are counting back from eof */
  123. static int    addeof_end;    /* Set when we are counting back from eof */
  124.  
  125. static FPOS_T    prevpage_loc;    /* Byte position of previous page header */
  126. static FPOS_T    curpage_loc;    /* Byte position of current page header */
  127. static FPOS_T    nextpage_loc;    /* Byte position of next page header */
  128.  
  129. /* File info */
  130.  
  131. static int    input_type;    /* 0 for file, 1 for stream */
  132. static PDFstrm    *pdfs;        /* PDF stream handle */
  133. static FILE    *MetaFile;    /* Actual metafile handle, for seeks etc */
  134.  
  135. static char    BaseName[80] = "", FileName[90] = "";
  136. static PLINT    is_family, member=1;
  137. static char    mf_magic[40], mf_version[40];
  138.  
  139. /* Dummy vars for reading stuff that is to be thrown away */
  140.  
  141. static U_CHAR    dum_uchar;
  142. static U_SHORT    dum_ushort;
  143. static float    dum_float;
  144.  
  145. /* Plot dimensions */
  146.  
  147. static short    xmin = 0;
  148. static short    xmax = PLMETA_X_OLD;
  149. static short    ymin = 0;
  150. static short    ymax = PLMETA_Y_OLD;
  151. static PLINT    xlen, ylen;
  152.  
  153. static float    pxlx = PIXEL_RES_X_OLD;
  154. static float    pxly = PIXEL_RES_Y_OLD;
  155.  
  156. static PLFLT    dev_xpmm, dev_ypmm;
  157. static PLINT    dev_xmin, dev_xmax, dev_ymin, dev_ymax, dev_xlen, dev_ylen;
  158. static PLFLT    vpxmin, vpxmax, vpxlen, vpymin, vpymax, vpylen;
  159.  
  160. /* Miscellaneous */
  161.  
  162. static U_CHAR     c_old, c1;
  163. static U_SHORT    npts;
  164. static int    direction_flag, isanum, at_eop;
  165. static char    num_buffer[20];
  166. static PLFLT    x[PL_MAXPOLY], y[PL_MAXPOLY];
  167.  
  168. /* Exit codes */
  169.  
  170. #define    EX_SUCCESS    0        /* success! */
  171. #define    EX_ARGSBAD    1        /* invalid args */
  172. #define    EX_BADFILE    2        /* invalid filename or contents */
  173.  
  174. /*----------------------------------------------------------------------*\
  175.  * Options data structure definition.
  176. \*----------------------------------------------------------------------*/
  177.  
  178. static PLOptionTable option_table[] = {
  179. {
  180.     "showall",            /* Turns on invisible options */
  181.     NULL,
  182.     NULL,
  183.     &mode_showall,
  184.     PL_OPT_BOOL | PL_OPT_ENABLED | PL_OPT_INVISIBLE,
  185.     "-showall",
  186.     "Turns on invisible options" },
  187. {
  188.     "h",            /* Help */
  189.     Opt_h,
  190.     NULL,
  191.     NULL,
  192.     PL_OPT_FUNC | PL_OPT_ENABLED,
  193.     "-h",
  194.     "Print out this message" },
  195. {
  196.     "v",            /* Version */
  197.     Opt_v,
  198.     NULL,
  199.     NULL,
  200.     PL_OPT_FUNC | PL_OPT_ENABLED,
  201.     "-v",
  202.     "Print out the plrender version number" },
  203. {
  204.     "i",            /* Input file */
  205.     Opt_i,
  206.     NULL,
  207.     NULL,
  208.     PL_OPT_FUNC | PL_OPT_ENABLED | PL_OPT_ARG,
  209.     "-i name",
  210.     "Input filename" },
  211. {
  212.     "f",            /* Filter option */
  213.     NULL,
  214.     NULL,
  215.     &input_type,
  216.     PL_OPT_BOOL | PL_OPT_ENABLED | PL_OPT_ARG,
  217.     "-f",
  218.     "Filter option -- equivalent to \"-i - -o -\"" },
  219. {
  220.     "b",            /* Beginning page number */
  221.     Opt_b,
  222.     NULL,
  223.     NULL,
  224.     PL_OPT_FUNC | PL_OPT_ENABLED | PL_OPT_ARG,
  225.     "-b number",
  226.     "Beginning page number" },
  227. {
  228.     "e",            /* End page number */
  229.     Opt_e,
  230.     NULL,
  231.     NULL,
  232.     PL_OPT_FUNC | PL_OPT_ENABLED | PL_OPT_ARG,
  233.     "-e number",
  234.     "End page number" },
  235. {
  236.     "p",            /* Specified page only */
  237.     Opt_p,
  238.     NULL,
  239.     NULL,
  240.     PL_OPT_FUNC | PL_OPT_ENABLED | PL_OPT_ARG,
  241.     "-p page",
  242.     "Plot given page only" },
  243. {
  244.     NULL,            /* option */
  245.     NULL,            /* handler */
  246.     NULL,            /* client data */
  247.     NULL,            /* address of variable to set */
  248.     0,                /* mode flag */
  249.     NULL,            /* short syntax */
  250.     NULL }            /* long syntax */
  251. };
  252.  
  253. static char *notes[] = {
  254. "All parameters must be white-space delimited, and plrender options override",
  255. "any plplot options of the same name.  If the \"-i\" flag is omitted the",
  256. "filename parameter must come last.  Specifying \"-\" for the input or output",
  257. "filename means use stdin or stdout, respectively.  Not all options valid",
  258. "with all drivers.  Please see the man pages for more detail.",
  259. NULL};
  260.  
  261. /* INDENT ON */
  262. /*----------------------------------------------------------------------*\
  263.  * main()
  264.  *
  265.  * plrender -- render a PLPLOT metafile.
  266. \*----------------------------------------------------------------------*/
  267.  
  268. int
  269. main(int argc, char *argv[])
  270. {
  271.     static U_CHAR c;
  272.  
  273. /* Initialize */
  274.  
  275.     Init(argc, argv);
  276.  
  277. /*
  278.  * Read & process metafile commands.
  279.  * If familying is turned on, the end of one member file is just treated as
  280.  * a page break assuming the next member file exists.
  281.  */
  282.     for (;;) {
  283.     c_old = c;
  284.     c = getcommand();
  285.  
  286.     if (c == CLOSE) {
  287.         if (is_family)
  288.         NextFamilyFile(&c);
  289.         if ( ! is_family)
  290.         break;
  291.     }
  292.  
  293.     if ((c == BOP || c == ADVANCE) && curdisp == disp_end)
  294.         break;
  295.  
  296.     process_next(c);
  297.     }
  298.  
  299. /* Done */
  300.  
  301.     pdf_close(pdfs);
  302.     if (strcmp(mf_version, "1993a") >= 0) 
  303.     plspause(0);
  304.  
  305.     plend();
  306.     exit(EX_SUCCESS);
  307. }
  308.  
  309. /*----------------------------------------------------------------------*\
  310.  *             Process the command loop
  311. \*----------------------------------------------------------------------*/
  312.  
  313. /*----------------------------------------------------------------------*\
  314.  * process_next()
  315.  *
  316.  * Process a command.
  317.  * Typically plrender issues commands to plplot much like an application
  318.  * program would.  This results in a more robust and flexible API.  On the
  319.  * other hand, it is sometimes necessary to directly call low-level plplot
  320.  * routines to achieve certain special effects, increase performance, or
  321.  * simplify the code.
  322. \*----------------------------------------------------------------------*/
  323.  
  324. static void
  325. process_next(U_CHAR c)
  326. {
  327.     switch ((int) c) {
  328.  
  329.     case INITIALIZE:
  330.     plr_init(c);
  331.     break;
  332.  
  333.     case LINE:
  334.     case LINETO:
  335.     case POLYLINE:
  336.     plr_line(c);
  337.     break;
  338.  
  339.     case EOP:
  340.     plr_eop(c);
  341.     break;
  342.  
  343.     case BOP:
  344.     plr_bop(c);
  345.     break;
  346.  
  347.     case CHANGE_STATE:
  348.     plr_state(getcommand());
  349.     break;
  350.  
  351.     case ESCAPE:
  352.     plr_esc(c);
  353.     break;
  354.  
  355. /* These are all commands that should be absent from current metafiles but */
  356. /* are recognized here for backward compatibility with old metafiles */
  357.  
  358.     case ADVANCE:
  359.     plr_eop(c);
  360.     plr_bop(c);
  361.     break;
  362.  
  363.     case NEW_WIDTH:
  364.     case NEW_COLOR0:
  365.     case NEW_COLOR1:
  366.     plr_state(c);
  367.     break;
  368.  
  369.     case SWITCH_TO_TEXT:
  370.     case SWITCH_TO_GRAPH:
  371.     break;
  372.  
  373.     default:
  374.     plexit("process_next: Unrecognized command");
  375.     }
  376. }
  377.  
  378. /*----------------------------------------------------------------------*\
  379.  * void plr_init()
  380.  *
  381.  * Handle initialization.
  382. \*----------------------------------------------------------------------*/
  383.  
  384. static void
  385. plr_init(U_CHAR c)
  386. {
  387.     float aspect, dev_aspect, ratio;
  388.  
  389.     dbug_enter("plr_init");
  390.  
  391. /* Register event handler */
  392.  
  393.     plsKeyEH(plr_KeyEH, NULL);
  394.  
  395. /* Start up plplot */
  396.  
  397.     plinit();
  398.     plP_gsub(&nsubx, &nsuby, &cursub);
  399.  
  400. /* Set aspect ratio to the natural ratio of the metafile coordinate system. */
  401.  
  402.     xlen = xmax - xmin;
  403.     ylen = ymax - ymin;
  404.  
  405.     aspect = (ylen / pxly) / (xlen / pxlx);
  406.  
  407. /* Aspect ratio of output device */
  408.  
  409.     plP_gphy(&dev_xmin, &dev_xmax, &dev_ymin, &dev_ymax);
  410.     plP_gpixmm(&dev_xpmm, &dev_ypmm);
  411.  
  412.     dev_xlen = dev_xmax - dev_xmin;
  413.     dev_ylen = dev_ymax - dev_ymin;
  414.  
  415.     dev_aspect = (dev_ylen / dev_ypmm) / (dev_xlen / dev_xpmm);
  416.  
  417.     if (dev_aspect <= 0.)
  418.     fprintf(stderr, "Aspect ratio error: dev_aspect = %f\n", dev_aspect);
  419.  
  420.     ratio = aspect / dev_aspect;
  421.  
  422. /* Default relative coordinate space */
  423.  
  424.     vpxlen = 1.0;
  425.     vpylen = 1.0;
  426.     vpxmin = 0.5 - vpxlen / 2.;
  427.     vpymin = 0.5 - vpylen / 2.;
  428.     vpxmax = vpxmin + vpxlen;
  429.     vpymax = vpymin + vpylen;
  430.  
  431. /*
  432.  * Construct viewport that preserves the aspect ratio of the original device
  433.  * (plmeta output file).  Thus you automatically get all physical coordinate
  434.  * plots to come out correctly.  Note: this could also be done using the
  435.  * driver interface function plsdimap.
  436.  */
  437.     if (ratio <= 0)
  438.     fprintf(stderr, "Aspect ratio error: ratio = %f\n", ratio);
  439.     else if (ratio < 1)
  440.     vpylen = ratio;
  441.     else
  442.     vpxlen = 1. / ratio;
  443.  
  444.     vpxmin = (1. - vpxlen) / 2.;
  445.     vpxmax = vpxmin + vpxlen;
  446.  
  447.     vpymin = (1. - vpylen) / 2.;
  448.     vpymax = vpymin + vpylen;
  449.  
  450. /* Seek to first page */
  451.  
  452.     cursub = nsubx*nsuby;
  453.     if (disp_beg > 1) {
  454.     if (no_pagelinks) 
  455.         plwarn("plrender: Metafile does not support page seeks");
  456.     else {
  457.         ReadPageHeader();
  458.         SeekToDisp(disp_beg);
  459.     }
  460.     }
  461. }
  462.  
  463. /*----------------------------------------------------------------------*\
  464.  * plr_line()
  465.  *
  466.  * Draw a line or polyline.
  467.  * Multiple connected lines (i.e. LINETO's) are collapsed into a polyline.
  468. \*----------------------------------------------------------------------*/
  469.  
  470. static void
  471. plr_line(U_CHAR c)
  472. {
  473.     npts = 1;
  474.  
  475.     switch ((int) c) {
  476.  
  477.     case LINE:
  478.     get_ncoords(x, y, 1);
  479.  
  480.     case LINETO:
  481.     for (;;) {
  482.         get_ncoords(x + npts, y + npts, 1);
  483.  
  484.         npts++;
  485.         if (npts == PL_MAXPOLY)
  486.         break;
  487.  
  488.         c1 = getcommand();
  489.         if (c1 != LINETO) {
  490.         ungetcommand(c1);
  491.         break;
  492.         }
  493.     }
  494.     break;
  495.  
  496.     case POLYLINE:
  497.     plm_rd( pdf_rd_2bytes(pdfs, &npts) );
  498.     get_ncoords(x, y, npts);
  499.     break;
  500.     }
  501.  
  502.     plline(npts, x, y);
  503.  
  504.     x[0] = x[npts - 1];
  505.     y[0] = y[npts - 1];
  506. }
  507.  
  508. /*----------------------------------------------------------------------*\
  509.  * get_ncoords()
  510.  *
  511.  * Read n coordinate vectors.
  512. \*----------------------------------------------------------------------*/
  513.  
  514. static void
  515. get_ncoords(PLFLT *x, PLFLT *y, PLINT n)
  516. {
  517.     short xs[PL_MAXPOLY], ys[PL_MAXPOLY];
  518.     PLINT i;
  519.  
  520.     plm_rd( pdf_rd_2nbytes(pdfs, (U_SHORT *) xs, n) );
  521.     plm_rd( pdf_rd_2nbytes(pdfs, (U_SHORT *) ys, n) );
  522.  
  523.     for (i = 0; i < n; i++) {
  524.     x[i] = xs[i];
  525.     y[i] = ys[i];
  526.     }
  527. }
  528.  
  529. /*----------------------------------------------------------------------*\
  530.  * plr_eop()
  531.  *
  532.  * Handle end of page.
  533.  * Here we run into a bit of difficulty with packed pages -- at the end
  534.  * there is no EOP operation done if the page is only partially full.
  535.  * So I peek ahead to see if the next operation is a CLOSE, and if so,
  536.  * push back the CLOSE and issue an EOP regardless.  
  537. \*----------------------------------------------------------------------*/
  538.  
  539. static void
  540. plr_eop(U_CHAR c)
  541. {
  542.     dbug_enter("plr_eop");
  543.  
  544.     c1 = getcommand();
  545.     ungetcommand(c1);
  546.     if (c1 == CLOSE)
  547.     end_of_page = 1;
  548.  
  549.     if (cursub == nsubx * nsuby)
  550.     end_of_page = 1;
  551.  
  552.     if (end_of_page == 1) {
  553.     at_eop = 1;
  554.     plP_eop();
  555.     at_eop = 0;
  556.     }
  557. }
  558.  
  559. /*----------------------------------------------------------------------*\
  560.  * plr_bop()
  561.  *
  562.  * Page/subpage advancement.
  563. \*----------------------------------------------------------------------*/
  564.  
  565. static void
  566. plr_bop(U_CHAR c)
  567. {
  568.     dbug_enter("plr_bop");
  569.  
  570.     ungetcommand(c);
  571.     ReadPageHeader();
  572.  
  573. /* Advance and setup the page or subpage */
  574.  
  575.     if (end_of_page) {
  576.     plP_bop();
  577.     end_of_page = 0;
  578.     seek_mode = 0;
  579.     }
  580.  
  581.     plP_ssub(nsubx, nsuby, cursub);
  582.     plP_setsub();
  583.  
  584.     plvpor(vpxmin, vpxmax, vpymin, vpymax);
  585.     plwind((PLFLT) xmin, (PLFLT) xmax, (PLFLT) ymin, (PLFLT) ymax);
  586. }
  587.  
  588. /*----------------------------------------------------------------------*\
  589.  * plr_state()
  590.  *
  591.  * Handle change in PLStream state (color, pen width, fill attribute, etc).
  592. \*----------------------------------------------------------------------*/
  593.  
  594. static void 
  595. plr_state(U_CHAR op)
  596. {
  597.     int i;
  598.  
  599.     dbug_enter("plr_state");
  600.  
  601.     switch (op) {
  602.  
  603.     case PLSTATE_WIDTH:{
  604.     U_SHORT width;
  605.  
  606.     plm_rd( pdf_rd_2bytes(pdfs, &width) );
  607.  
  608.     plwid(width);
  609.     break;
  610.     }
  611.  
  612.     case PLSTATE_COLOR0:{
  613.     U_SHORT icol;
  614.     U_CHAR icol0, r, g, b;
  615.  
  616.     if (strcmp(mf_version, "1993a") >= 0) {
  617.         plm_rd( pdf_rd_1byte(pdfs, &icol0) );
  618.  
  619.         if (icol0 == PL_RGB_COLOR) {
  620.         plm_rd( pdf_rd_1byte(pdfs, &r) );
  621.         plm_rd( pdf_rd_1byte(pdfs, &g) );
  622.         plm_rd( pdf_rd_1byte(pdfs, &b) );
  623.         plrgb1(r, g, b);
  624.         }
  625.         else {
  626.         plcol(icol0);
  627.         }
  628.     }
  629.     else {
  630.         plm_rd( pdf_rd_2bytes(pdfs, &icol) );
  631.         plcol(icol);
  632.     }
  633.     break;
  634.     }
  635.  
  636.     case PLSTATE_COLOR1:{
  637.     U_SHORT icol1;
  638.     PLFLT col1;
  639.  
  640.     plm_rd( pdf_rd_2bytes(pdfs, &icol1) );
  641.     col1 = (float) icol1 / (float) plsc->ncol1;
  642.     plcol1(col1);
  643.     break;
  644.     }
  645.  
  646.     case PLSTATE_FILL:{
  647.     signed char patt;
  648.  
  649.     plm_rd( pdf_rd_1byte(pdfs, (U_CHAR *) &patt) );
  650.     plpsty(patt);
  651.     break;
  652.     }
  653.  
  654.     case PLSTATE_CMAP0:{
  655.     U_CHAR ncol0;
  656.  
  657.     plm_rd(pdf_rd_1byte(pdfs, &ncol0));
  658.     plsc->ncol0 = ncol0;
  659.     for (i = 0; i < plsc->ncol0; i++) {
  660.         plm_rd(pdf_rd_1byte(pdfs, &plsc->cmap0[i].r));
  661.         plm_rd(pdf_rd_1byte(pdfs, &plsc->cmap0[i].g));
  662.         plm_rd(pdf_rd_1byte(pdfs, &plsc->cmap0[i].b));
  663.         plsc->cmap0setcol[i] = 1;
  664.     }
  665.     break;
  666.     }
  667.  
  668.     case PLSTATE_CMAP1:{
  669.     U_SHORT ncol1;
  670.  
  671.     plm_rd(pdf_rd_2bytes(pdfs, &ncol1));
  672.     plsc->ncol1 = ncol1;
  673.     for (i = 0; i < plsc->ncol1; i++) {
  674.         plm_rd(pdf_rd_1byte(pdfs, &plsc->cmap1[i].r));
  675.         plm_rd(pdf_rd_1byte(pdfs, &plsc->cmap1[i].g));
  676.         plm_rd(pdf_rd_1byte(pdfs, &plsc->cmap1[i].b));
  677.     }
  678.     plsc->cmap1set = 1;
  679.     break;
  680.     }
  681.     }
  682. }
  683.  
  684. /*----------------------------------------------------------------------*\
  685.  * plr_esc()
  686.  *
  687.  * Handle all escape functions.
  688. \*----------------------------------------------------------------------*/
  689.  
  690. static void
  691. plr_esc(U_CHAR c)
  692. {
  693.     U_CHAR op;
  694.  
  695.     dbug_enter("plr_esc");
  696.  
  697.     plm_rd( pdf_rd_1byte(pdfs, &op) );
  698.  
  699.     switch (op) {
  700.  
  701.     case PLESC_FILL:
  702.     plresc_fill();
  703.     break;
  704.  
  705. /* These are all commands that should be absent from current metafiles but */
  706. /* are recognized here for backward compatibility with old metafiles */
  707.  
  708.     case PLESC_SET_RGB:
  709.     plresc_rgb();
  710.     return;
  711.  
  712.     case PLESC_ALLOC_NCOL:
  713.     plresc_ancol();
  714.     return;
  715.  
  716.     case PLESC_SET_LPB:
  717.     plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  718.     plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  719.     plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  720.     plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  721.     return;
  722.     }
  723. }
  724.  
  725. /*----------------------------------------------------------------------*\
  726.  * plresc_fill()
  727.  *
  728.  * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  729. \*----------------------------------------------------------------------*/
  730.  
  731. static void
  732. plresc_fill(void)
  733. {
  734.     dbug_enter("plresc_fill");
  735.  
  736.     plm_rd( pdf_rd_2bytes(pdfs, &npts) );
  737.     get_ncoords(x, y, npts);
  738.     plfill(npts, x, y);
  739. }
  740.  
  741. /*----------------------------------------------------------------------*\
  742.  * plresc_rgb()
  743.  *
  744.  * Process escape function for RGB color selection.
  745.  * Note that RGB color selection is no longer handled this way by
  746.  * plplot but we must handle it here for old metafiles.
  747. \*----------------------------------------------------------------------*/
  748.  
  749. static void
  750. plresc_rgb(void)
  751. {
  752.     float red, green, blue;
  753.     U_SHORT ired, igreen, iblue;
  754.  
  755.     dbug_enter("plresc_rgb");
  756.  
  757.     plm_rd( pdf_rd_2bytes(pdfs, &ired) );
  758.     plm_rd( pdf_rd_2bytes(pdfs, &igreen) );
  759.     plm_rd( pdf_rd_2bytes(pdfs, &iblue) );
  760.  
  761.     red = (double) ired / 65535.;
  762.     green = (double) igreen / 65535.;
  763.     blue = (double) iblue / 65535.;
  764.  
  765.     plrgb(red, green, blue);
  766. }
  767.  
  768. /*----------------------------------------------------------------------*\
  769.  * plresc_ancol()
  770.  *
  771.  * Process escape function for named color table allocation.
  772.  * OBSOLETE -- just read the info and move on.
  773. \*----------------------------------------------------------------------*/
  774.  
  775. static void
  776. plresc_ancol(void)
  777. {
  778.     U_CHAR icolor;
  779.     char name[80];
  780.  
  781.     dbug_enter("plresc_ancol");
  782.  
  783.     plm_rd( pdf_rd_1byte(pdfs, &icolor) );
  784.     plm_rd( pdf_rd_header(pdfs, name) );
  785. }
  786.  
  787. /*----------------------------------------------------------------------*\
  788.  *             Support routines
  789. \*----------------------------------------------------------------------*/
  790.  
  791. /*----------------------------------------------------------------------*\
  792.  * NextFamilyFile()
  793.  *
  794.  * Start the next family if it exists.
  795. \*----------------------------------------------------------------------*/
  796.  
  797. static void
  798. NextFamilyFile(U_CHAR *c)
  799. {
  800.     dbug_enter("NextFamilyFile");
  801.  
  802.     (void) fclose(MetaFile);
  803.     member++;
  804.     (void) sprintf(FileName, "%s.%i", BaseName, (int) member);
  805.  
  806.     if ((MetaFile = fopen(FileName, "rb")) == NULL) {
  807.     is_family = 0;
  808.     return;
  809.     }
  810.     if (ReadFileHeader()) {
  811.     is_family = 0;
  812.     return;
  813.     }
  814.     pdfs->file = MetaFile;
  815.  
  816. /*
  817.  * If the family file was created correctly, the first instruction in the
  818.  * file (after state information) MUST be an INITIALIZE.  We throw this
  819.  * away and put a page advance in its place. 
  820.  */
  821.  
  822.     *c = getcommand();
  823.     while (*c == CHANGE_STATE) {
  824.     plr_state(getcommand());
  825.     *c = getcommand();
  826.     }
  827.  
  828.     if (*c != INITIALIZE)
  829.     fprintf(stderr,
  830.         "Warning, first instruction in member file not an INIT\n");
  831.     else
  832.     *c = ADVANCE;
  833. }
  834.  
  835. /*----------------------------------------------------------------------*\
  836.  * getcommand()
  837.  *
  838.  * Read & return the next command
  839. \*----------------------------------------------------------------------*/
  840.  
  841. static U_CHAR
  842. getcommand(void)
  843. {
  844.     int c;
  845.  
  846.     c = getc(MetaFile);
  847.     if (c == EOF)
  848.     plexit("getcommand: Unable to read from MetaFile");
  849.  
  850.     return (U_CHAR) c;
  851. }
  852.  
  853. /*----------------------------------------------------------------------*\
  854.  * ungetcommand()
  855.  *
  856.  * Push back the last command read.
  857. \*----------------------------------------------------------------------*/
  858.  
  859. static void
  860. ungetcommand(U_CHAR c)
  861. {
  862.     if (ungetc(c, MetaFile) == EOF)
  863.     plexit("ungetcommand: Unable to push back character");
  864. }
  865.  
  866. /*----------------------------------------------------------------------*\
  867.  * plr_KeyEH()
  868.  *
  869.  * Keyboard event handler.  For mapping keyboard sequences to commands
  870.  * not usually supported by plplot, such as seeking around in the
  871.  * metafile.  Recognized commands:
  872.  *
  873.  * <Backspace>    |
  874.  * <Delete>    | Back page
  875.  * <Page up>    |
  876.  *
  877.  * +<num><CR>    Seek forward <num> pages.
  878.  * -<num><CR>    Seek backward <num> pages.
  879.  *
  880.  * <num><CR>    Seek to page <num>.
  881.  * --<num><CR>    Seek to <num> pages before EOF.
  882.  *
  883.  * Both <BS> and <DEL> are recognized for a back-page since the target
  884.  * system may use either as its erase key.  <Page Up> is present on some
  885.  * keyboards (different from keypad key).
  886.  *
  887.  * No user data is passed in this case, although a test case is
  888.  * illustrated. 
  889.  *
  890.  * Illegal input is ignored.
  891. \*----------------------------------------------------------------------*/
  892.  
  893. static void
  894. plr_KeyEH(PLKey *key, void *user_data, int *p_exit_eventloop)
  895. {
  896.     char *tst = (char *) user_data;
  897.     int input_num, dun_seek = 0, terminator_seen = 0;
  898.  
  899. #ifdef DEBUG
  900.     fprintf(stderr, "key->code = %x\n", key->code);
  901. #endif
  902.  
  903. /* TEST */
  904.  
  905.     if (tst != NULL) {
  906.     pltext();
  907.     fprintf(stderr, "tst string: %s\n", tst);
  908.     plgra();
  909.     }
  910.  
  911. /* The rest deals with seeking only; so we return if it is disabled */
  912.  
  913.     if (no_pagelinks || (input_type > 0)) 
  914.     return;
  915.  
  916. /* Forward (+) or backward (-) */
  917.  
  918.     if (key->string[0] == '+')
  919.     direction_flag++;
  920.  
  921.     else if (key->string[0] == '-')
  922.     direction_flag--;
  923.  
  924. /* If a number, store into num_buffer */
  925.  
  926.     if (isdigit(key->string[0])) {
  927.     isanum = TRUE;
  928.     (void) strncat(num_buffer, key->string, (20-strlen(num_buffer)));
  929.     }
  930.  
  931. /* 
  932.  * Seek to specified page, or page advance.
  933.  * Not done until user hits <return>.
  934.  * Need to check for both <LF> and <CR> for portability.
  935.  */
  936.     if (key->code == PLK_Return ||
  937.     key->code == PLK_Linefeed ||
  938.     key->code == PLK_Next)
  939.     {
  940.     terminator_seen = 1;
  941.     if (isanum) {
  942.         input_num = atoi(num_buffer);
  943.         if (input_num == 0) {
  944.         if (strcmp(num_buffer, "0"))
  945.             input_num = -1;
  946.         }
  947.         if (input_num >= 0) {
  948.         if (direction_flag == 0)
  949.             target_disp = input_num;
  950.         else if (direction_flag == 1)
  951.             target_disp = curdisp + input_num;
  952.         else if (direction_flag == -1)
  953.             target_disp = curdisp - input_num;
  954.         else if (direction_flag == -2)
  955.             target_disp = pages - input_num;
  956.  
  957.         SeekToDisp(target_disp);
  958.         dun_seek = 1;
  959.         }
  960.     }
  961.     else {
  962.         target_disp = curdisp + 1;
  963.         SeekToDisp(target_disp);
  964.         dun_seek = 1;
  965.     }
  966.     }
  967.  
  968. /* Page backward */
  969.  
  970.     if (key->code == PLK_BackSpace ||
  971.     key->code == PLK_Delete ||
  972.     key->code == PLK_Prior) 
  973.     {
  974.     terminator_seen = 1;
  975.     target_disp = curdisp - 1;
  976.     SeekToDisp(target_disp);
  977.     dun_seek = 1;
  978.     }
  979.  
  980. /* Cleanup */
  981.  
  982.     if (terminator_seen) {
  983.     num_buffer[0] = '\0';
  984.     direction_flag = 0;
  985.     isanum = 0;
  986.     key->code = 0;
  987.     }
  988.     if (dun_seek && at_eop)
  989.     *p_exit_eventloop = TRUE;
  990. }
  991.  
  992. /*----------------------------------------------------------------------*\
  993.  * SeekToDisp()
  994.  *
  995.  * Seek to 'target_disp' displayed page.  
  996.  *
  997.  * Several things combine to make this much harder than one would think.
  998.  * These include: taking packed pages into account, seeking from mid-plot,
  999.  * and multiple contiguous seek events.  All in all a disgusting mess.
  1000.  *
  1001.  * When this routine is called we are probably at the end of a page, but
  1002.  * maybe not (e.g. if the user hit <Backspace> or <Return> in the middle
  1003.  * of the screen update, and the driver immediately processes the event).
  1004.  * Also we might be at the end of the file.  So only if we are right
  1005.  * before the desired displayed page AND the end of page condition is met,
  1006.  * we are done.
  1007.  *
  1008.  * When reference is made to a displayed (i.e. possibly packed) page, I
  1009.  * will use variables with the "disp" tag.  For metafile pages, I will
  1010.  * use "page".  I could have used the word "plot" somewhere but I am
  1011.  * reserving that for future uses.
  1012.  *
  1013.  * To deal with multiple contiguous seek events (e.g. the user hits
  1014.  * <Backspace> twice before the renderer has a chance to respond) the
  1015.  * "seek_mode" variable was found to be necessary.
  1016. \*----------------------------------------------------------------------*/
  1017.  
  1018. static void
  1019. SeekToDisp(long target_disp)
  1020. {
  1021.     dbug_enter("SeekToDisp");
  1022.  
  1023. /* Determine target_page */
  1024. /* Needs to be the last subpage on the preceding displayed page,  */
  1025. /* so we subtract 1 unless the last seek is still active */
  1026.  
  1027.     if ( ! seek_mode)
  1028.     --target_disp;
  1029.  
  1030.     target_page = target_disp * nsubx * nsuby;
  1031.     delta = target_page - curpage;
  1032.     seek_mode = 1;
  1033.  
  1034. /* Handle special cases first -- none of these require seeks. */
  1035. /* An example of how each condition might arise is given. */
  1036.  
  1037. /* <Return> at the end of a page */
  1038.  
  1039.     if ((delta == 0) && at_eop)
  1040.     return;
  1041.  
  1042. /* <Return> while drawing the last page */
  1043.  
  1044.     if ((delta >= 0) && (nextpage_loc == 0))
  1045.     return;
  1046.  
  1047. /* Anything else requires at least one seek */
  1048.  
  1049. #ifdef DEBUG
  1050.     fprintf(stderr,
  1051.         "Before seek: target_page = %d, curpage = %d, curdisp = %d\n",
  1052.         target_page, curpage, curdisp);
  1053. #endif
  1054.  
  1055. /* <Return> while drawing any page but the last */
  1056.  
  1057.     if (delta == 0) {
  1058.     SeekToNextPage();
  1059.     goto done;
  1060.     }
  1061.  
  1062. /* Prepare for backward seeks by seeking to the start of the current page */
  1063. /* If on the first page, we're done */
  1064.  
  1065.     if (delta < 0) {
  1066.     SeekToCurPage();
  1067.     if (prevpage_loc == 0)
  1068.         goto done;
  1069.     }
  1070.  
  1071. /* Now seek by pages until we arrive at the target page */
  1072.  
  1073.     while (delta != 0)
  1074.     SeekOnePage();
  1075.  
  1076.  done:
  1077. #ifdef DEBUG
  1078.     fprintf(stderr, "After seek: curpage = %d, curdisp = %d, cursub = %d\n",
  1079.         curpage, curdisp, cursub);
  1080. #endif
  1081.  
  1082.     end_of_page = 1;
  1083.     return;
  1084. }
  1085.  
  1086. /*----------------------------------------------------------------------*\
  1087.  * SeekOnePage()
  1088.  *
  1089.  * Seeks one page in appropriate direction, and updates delta.
  1090.  * For out of bounds seeks, just stay on the boundary page (first or last).
  1091. \*----------------------------------------------------------------------*/
  1092.  
  1093. static void
  1094. SeekOnePage(void)
  1095. {
  1096.     if (delta > 0) {
  1097.     if (nextpage_loc == 0) {
  1098.         SeekToCurPage();
  1099.         delta = 0;
  1100.         return;
  1101.     }
  1102.     SeekToNextPage();
  1103.     }
  1104.     else {
  1105.     if (prevpage_loc == 0) {
  1106.         SeekToCurPage();
  1107.         delta = 0;
  1108.         return;
  1109.     }
  1110.     SeekToPrevPage();
  1111.     }
  1112.  
  1113.     delta = target_page - curpage;
  1114.  
  1115. #ifdef DEBUG
  1116.     fprintf(stderr, "Now at page %d, disp %d, delta %d\n",
  1117.         curpage, curdisp, delta);
  1118. #endif
  1119.     return;
  1120. }
  1121.  
  1122. /*----------------------------------------------------------------------*\
  1123.  * SeekToCurPage()
  1124.  *
  1125.  * Seeks to beginning of current page, changing the page counters if
  1126.  * we pass a page boundary in the process.  Are you sufficiently sick
  1127.  * yet?  I know I am.
  1128. \*----------------------------------------------------------------------*/
  1129.  
  1130. static void
  1131. SeekToCurPage(void)
  1132. {
  1133.     FPOS_T loc;
  1134.  
  1135.     if (pl_fgetpos(MetaFile, &loc))
  1136.     plexit("plrender: fgetpos call failed");
  1137.  
  1138.     if (loc != curpage_loc) 
  1139.     PageDecr();
  1140.  
  1141.     SeekTo(curpage_loc);
  1142. }
  1143.  
  1144. /*----------------------------------------------------------------------*\
  1145.  * SeekToNextPage()
  1146.  *
  1147.  * Seeks to beginning of next page, changing the page counters if
  1148.  * we pass a page boundary in the process.  
  1149. \*----------------------------------------------------------------------*/
  1150.  
  1151. static void
  1152. SeekToNextPage(void)
  1153. {
  1154.     FPOS_T loc;
  1155.  
  1156.     if (pl_fgetpos(MetaFile, &loc))
  1157.     plexit("plrender: fgetpos call failed");
  1158.  
  1159.     if (loc == curpage_loc) 
  1160.     PageIncr();
  1161.  
  1162.     SeekTo(nextpage_loc);
  1163. }
  1164.  
  1165. /*----------------------------------------------------------------------*\
  1166.  * SeekToPrevPage()
  1167.  *
  1168.  * Seeks to beginning of previous page, changing page counters to
  1169.  * take into account each page header we skip over.  Getting sicker
  1170.  * all the time..
  1171. \*----------------------------------------------------------------------*/
  1172.  
  1173. static void
  1174. SeekToPrevPage(void)
  1175. {
  1176.     FPOS_T loc;
  1177.  
  1178.     if (pl_fgetpos(MetaFile, &loc))
  1179.     plexit("plrender: fgetpos call failed");
  1180.  
  1181.     if (loc != curpage_loc) 
  1182.     PageDecr();
  1183.  
  1184.     SeekTo(prevpage_loc);
  1185.     PageDecr();
  1186. }
  1187.  
  1188. /*----------------------------------------------------------------------*\
  1189.  * SeekTo()
  1190.  *
  1191.  * Seeks to specified location, updating page links.
  1192. \*----------------------------------------------------------------------*/
  1193.  
  1194. static void
  1195. SeekTo(FPOS_T loc)
  1196. {
  1197. #ifdef DEBUG
  1198.     fprintf(stderr, "Seeking to: %d\n", loc);
  1199. #endif
  1200.  
  1201.     doseek(loc);
  1202.  
  1203. /* Update page links */
  1204.  
  1205.     ReadPageHeader();
  1206.     doseek(curpage_loc);
  1207.     PageDecr();
  1208. }
  1209.  
  1210. /*----------------------------------------------------------------------*\
  1211.  * Utility functions:
  1212.  *
  1213.  * doseek()    Seeks to the specified location in the file.
  1214.  * PageIncr()    Increments page counters
  1215.  * PageDecr()    Decrements page counters
  1216. \*----------------------------------------------------------------------*/
  1217.  
  1218. static void
  1219. doseek(FPOS_T loc)
  1220. {
  1221.     if (pl_fsetpos(MetaFile, &loc))
  1222.     plexit("plrender: fsetpos call failed");
  1223. }
  1224.  
  1225. static void
  1226. PageDecr(void)
  1227. {
  1228.     curpage--;
  1229.     cursub--;
  1230.     if (cursub < 1) {
  1231.     cursub = nsubx * nsuby;
  1232.     curdisp--;
  1233.     }
  1234. }
  1235.  
  1236. static void
  1237. PageIncr(void)
  1238. {
  1239.     cursub++;
  1240.     curpage++;
  1241.     if (cursub > nsubx * nsuby) {
  1242.     cursub = 1;
  1243.     curdisp++;
  1244.     }
  1245. }
  1246.  
  1247. /* Yes, finally done with the seek routines.  
  1248.     "BELIEVE IT!" - John Walker, from "Buckaroo Bonzai" */
  1249.  
  1250. /*----------------------------------------------------------------------*\
  1251.  * ReadPageHeader()
  1252.  *
  1253.  * Reads the metafile, processing page header info.
  1254.  * Assumes the file pointer is positioned immediately before a PAGE.
  1255. \*----------------------------------------------------------------------*/
  1256.  
  1257. static void
  1258. ReadPageHeader(void)
  1259. {
  1260.     U_CHAR c;
  1261.     U_SHORT page;
  1262.     U_LONG prevpage, nextpage;
  1263.  
  1264.     dbug_enter("ReadPageHeader");
  1265.  
  1266. /* Read page header */
  1267.  
  1268.     if (input_type == 0) {
  1269.     if (pl_fgetpos(MetaFile, &curpage_loc))
  1270.         plexit("plrender: fgetpos call failed");
  1271.     }
  1272.  
  1273.     c = getcommand();
  1274.     if (c != PAGE && c != ADVANCE) 
  1275.     plexit("plrender: page advance expected; none found");
  1276.  
  1277. /* Update page/subpage counters and update page links */
  1278.  
  1279.     PageIncr();
  1280.  
  1281.     if (strcmp(mf_version, "1992a") >= 0) {
  1282.     if (strcmp(mf_version, "1993a") >= 0) {
  1283.         plm_rd( pdf_rd_2bytes(pdfs, &page) );
  1284.         plm_rd( pdf_rd_4bytes(pdfs, &prevpage) );
  1285.         plm_rd( pdf_rd_4bytes(pdfs, &nextpage) );
  1286.         prevpage_loc = prevpage;
  1287.         nextpage_loc = nextpage;
  1288.     }
  1289.     else {
  1290.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1291.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1292.     }
  1293.     }
  1294.  
  1295. #ifdef DEBUG
  1296.     fprintf(stderr, "Now at page %d, disp %d\n", curpage, curdisp);
  1297. #endif
  1298. }
  1299.  
  1300. /*----------------------------------------------------------------------*\
  1301.  * Init()
  1302.  *
  1303.  * Do initialization for main().
  1304. \*----------------------------------------------------------------------*/
  1305.  
  1306. static void
  1307. Init(int argc, char **argv)
  1308. {
  1309.     int i, status;
  1310.  
  1311.     dbug_enter("Init");
  1312.  
  1313. /* Process plrender command line options */
  1314.  
  1315.     status = plParseOpts(&argc, argv, mode_plrender, option_table, Usage);
  1316.  
  1317. /*
  1318.  * We want the plplot command line options to supercede their possible
  1319.  * counterparts in the metafile header.  So we defer parsing the
  1320.  * rest of the command line until after we process the metafile header.
  1321.  */
  1322.  
  1323.     OpenMetaFile(&argc, argv);
  1324.     pdfs = pdf_finit(MetaFile);
  1325.  
  1326. /* Read header */
  1327.  
  1328.     if (ReadFileHeader())
  1329.     exit(EX_BADFILE);
  1330.  
  1331. /* Other miscellaneous housekeeping */
  1332.  
  1333.     if (addeof_beg) disp_beg += pages;
  1334.     if (addeof_end) disp_end += pages;
  1335.  
  1336.     plSetInternalOpt("-tcl_cmd", "set plw_create_proc plr_create");
  1337.  
  1338. /* Finally, give the rest of the command line to plplot to process. */
  1339.  
  1340.     status = plParseInternalOpts(&argc, argv, mode_plplot);
  1341.  
  1342. /* 
  1343.  * At this point the only remaining argument in argv should be the program
  1344.  * name (which should be first).  Anything else is an error.  Handle illegal
  1345.  * flags first.
  1346.  */
  1347.  
  1348.     for (i = 1; i < argc; i++) {
  1349.     if ((argv)[i][0] == '-')
  1350.         Usage(argv[i]);
  1351.     }
  1352.  
  1353. /* These must be extraneous file names */
  1354.  
  1355.     if (i > 1) {
  1356.     fprintf(stderr, "Only one filename argument accepted.\n");
  1357.     Usage("");
  1358.     }
  1359. }
  1360.  
  1361. /*----------------------------------------------------------------------*\
  1362.  * OpenMetaFile()
  1363.  *
  1364.  * Attempts to open the named file.
  1365.  * If the output file isn't already determined via the -i or -f flags, 
  1366.  * we assume it's the last argument in argv[]. 
  1367. \*----------------------------------------------------------------------*/
  1368.  
  1369. static void
  1370. OpenMetaFile(int *p_argc, char **argv)
  1371. {
  1372.     char name[70];
  1373.  
  1374.     dbug_enter("OpenMetaFile");
  1375.  
  1376.     if ( ! strcmp(FileName, "-"))
  1377.     input_type = 1;
  1378.  
  1379.     if (input_type == 1)
  1380.     MetaFile = stdin;
  1381.  
  1382.     else {
  1383.     if (*FileName == '\0') {
  1384.         if (*p_argc > 1) {
  1385.         strncpy(FileName, argv[*p_argc-1], sizeof(FileName) - 1);
  1386.         FileName[sizeof(FileName) - 1] = '\0';
  1387.         argv[*p_argc] = NULL;
  1388.         (*p_argc)--;
  1389.         }
  1390.     }
  1391.     if (*FileName == '\0') {
  1392.         fprintf(stderr, "%s: No filename specified.\n", program_name);
  1393.         Usage("");
  1394.         exit(EX_ARGSBAD);
  1395.     }
  1396.  
  1397. /*
  1398.  * Try to read named Metafile.  The following cases are checked in order:
  1399.  *    <FileName>
  1400.  *    <FileName>.1
  1401.  *    <FileName>.plm
  1402.  *    <FileName>.plm.1
  1403.  */
  1404. #ifdef DEBUG
  1405.     fprintf(stderr, "Trying to open metafile %s.\n", FileName);
  1406. #endif
  1407.     strncpy(name, FileName, sizeof(name) - 1);
  1408.     name[sizeof(name) - 1] = '\0';
  1409.  
  1410.     if ((MetaFile = fopen(FileName, "rb")) != NULL) {
  1411.         return;
  1412.     }
  1413.  
  1414.     (void) sprintf(FileName, "%s.%i", name, (int) member);
  1415.     if ((MetaFile = fopen(FileName, "rb")) != NULL) {
  1416.         (void) sprintf(BaseName, "%s", name);
  1417.         is_family = 1;
  1418.         return;
  1419.     }
  1420.  
  1421.     (void) sprintf(FileName, "%s.plm", name);
  1422.     if ((MetaFile = fopen(FileName, "rb")) != NULL) {
  1423.         return;
  1424.     }
  1425.  
  1426.     (void) sprintf(FileName, "%s.plm.%i", name, (int) member);
  1427.     if ((MetaFile = fopen(FileName, "rb")) != NULL) {
  1428.         (void) sprintf(BaseName, "%s.plm", name);
  1429.         is_family = 1;
  1430.         return;
  1431.     }
  1432.  
  1433.     fprintf(stderr, "Unable to open the requested metafile.\n");
  1434.     Usage("");
  1435.     exit(EX_BADFILE);
  1436.     }
  1437. }
  1438.  
  1439. /*----------------------------------------------------------------------*\
  1440.  * ReadFileHeader()
  1441.  *
  1442.  * Checks file header.  Returns 1 if an error occured.
  1443. \*----------------------------------------------------------------------*/
  1444.  
  1445. static int
  1446. ReadFileHeader(void)
  1447. {
  1448.     char tag[80];
  1449.  
  1450.     dbug_enter("ReadFileHeader");
  1451.  
  1452. /* Read label field of header to make sure file is a PLPLOT metafile */
  1453.  
  1454.     plm_rd( pdf_rd_header(pdfs, mf_magic) );
  1455.     if (strcmp(mf_magic, PLMETA_HEADER)) {
  1456.     fprintf(stderr, "Not a PLPLOT metafile!\n");
  1457.     return 1;
  1458.     }
  1459.  
  1460. /* Read version field of header.  We need to check that we can read the
  1461.    metafile, in case this is an old version of plrender. */
  1462.  
  1463.     plm_rd( pdf_rd_header(pdfs, mf_version) );
  1464.     if (strcmp(mf_version, PLMETA_VERSION) > 0) {
  1465.     fprintf(stderr,
  1466.         "Error: incapable of reading metafile version %s.\n", mf_version);
  1467.     fprintf(stderr, "Please obtain a newer copy of plrender.\n");
  1468.     return 1;
  1469.     }
  1470.  
  1471. /* Disable page seeking on versions without page links */
  1472.  
  1473.     if (strcmp(mf_version, "1993a") < 0) 
  1474.     no_pagelinks=1;
  1475.  
  1476. /* Return if metafile older than version 1992a (no tagged info). */
  1477.  
  1478.     if (strcmp(mf_version, "1992a") < 0) {
  1479.     return 0;
  1480.     }
  1481.  
  1482. /* Read tagged initialization info. */
  1483. /* This is an easy way to guarantee backward compatibility. */
  1484.  
  1485.     for (;;) {
  1486.     plm_rd( pdf_rd_header(pdfs, tag) );
  1487.     if (*tag == '\0')
  1488.         break;
  1489.  
  1490.     if ( ! strcmp(tag, "pages")) {
  1491.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1492.         pages = dum_ushort;
  1493.         continue;
  1494.     }
  1495.  
  1496.     if ( ! strcmp(tag, "xmin")) {
  1497.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1498.         xmin = dum_ushort;
  1499.         continue;
  1500.     }
  1501.  
  1502.     if ( ! strcmp(tag, "xmax")) {
  1503.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1504.         xmax = dum_ushort;
  1505.         continue;
  1506.     }
  1507.  
  1508.     if ( ! strcmp(tag, "ymin")) {
  1509.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1510.         ymin = dum_ushort;
  1511.         continue;
  1512.     }
  1513.  
  1514.     if ( ! strcmp(tag, "ymax")) {
  1515.         plm_rd( pdf_rd_2bytes(pdfs, &dum_ushort) );
  1516.         ymax = dum_ushort;
  1517.         continue;
  1518.     }
  1519.  
  1520.     if ( ! strcmp(tag, "pxlx")) {
  1521.         plm_rd( pdf_rd_ieeef(pdfs, &pxlx) );
  1522.         continue;
  1523.     }
  1524.  
  1525.     if ( ! strcmp(tag, "pxly")) {
  1526.         plm_rd( pdf_rd_ieeef(pdfs, &pxly) );
  1527.         continue;
  1528.     }
  1529.  
  1530.     if ( ! strcmp(tag, "width")) {
  1531.         plm_rd( pdf_rd_1byte(pdfs, &dum_uchar) );
  1532.         plwid(dum_uchar);
  1533.         continue;
  1534.     }
  1535.  
  1536. /* Obsolete tags */
  1537.  
  1538.     if ( ! strcmp(tag, "orient")) {
  1539.         plm_rd( pdf_rd_1byte(pdfs, &dum_uchar) );
  1540.         continue;
  1541.     }
  1542.  
  1543.     if ( ! strcmp(tag, "aspect")) {
  1544.         plm_rd( pdf_rd_ieeef(pdfs, &dum_float) );
  1545.         continue;
  1546.     }
  1547.  
  1548.     fprintf(stderr, "Unrecognized PLPLOT metafile header tag.\n");
  1549.     exit(EX_BADFILE);
  1550.     }
  1551.  
  1552.     return 0;
  1553. }
  1554.  
  1555. /*----------------------------------------------------------------------*\
  1556.  * Help()
  1557.  *
  1558.  * Print long help message.
  1559. \*----------------------------------------------------------------------*/
  1560.  
  1561. static void
  1562. Help(void)
  1563. {
  1564.     dbug_enter("Help");
  1565.  
  1566.     fprintf(stderr,
  1567.         "\nUsage:\n        %s [%s options] [plplot options] [filename]\n",
  1568.         program_name, program_name);
  1569.  
  1570.     if (mode_showall)
  1571.     mode_plplot |= PL_PARSE_SHOWALL;
  1572.  
  1573.     myHelp();
  1574.     plHelp(mode_plplot);
  1575.     myNotes();
  1576.  
  1577.     exit(1);
  1578. }
  1579.  
  1580. /*----------------------------------------------------------------------*\
  1581.  * myHelp()
  1582.  *
  1583.  * Print long help message associated with plrender options only.
  1584. \*----------------------------------------------------------------------*/
  1585.  
  1586. static void
  1587. myHelp(void)
  1588. {
  1589.     PLOptionTable *tab;
  1590.  
  1591.     fprintf(stderr, "\n%s options:\n", program_name);
  1592.     for (tab = option_table; tab->opt; tab++) {
  1593.     if ( ! (tab->mode & PL_OPT_ENABLED))
  1594.         continue;
  1595.  
  1596.     if ( ! mode_showall && (tab->mode & PL_OPT_INVISIBLE))
  1597.         continue;
  1598.  
  1599.     if (tab->desc == NULL)
  1600.         continue;
  1601.  
  1602.     if (tab->mode & PL_OPT_INVISIBLE) 
  1603.         fprintf(stderr, " *  %-20s %s\n", tab->syntax, tab->desc);
  1604.     else 
  1605.         fprintf(stderr, "    %-20s %s\n", tab->syntax, tab->desc);
  1606.     }
  1607. }
  1608.  
  1609. /*----------------------------------------------------------------------*\
  1610.  * myNotes()
  1611.  *
  1612.  * Print notes associated with long help message for plrender.
  1613. \*----------------------------------------------------------------------*/
  1614.  
  1615. static void
  1616. myNotes(void)
  1617. {
  1618.     char **cpp;
  1619.  
  1620.     putc('\n', stderr);
  1621.     for (cpp = notes; *cpp; cpp++) {
  1622.     fputs(*cpp, stderr);
  1623.     putc('\n', stderr);
  1624.     }
  1625.     putc('\n', stderr);
  1626. }
  1627.  
  1628. /*----------------------------------------------------------------------*\
  1629.  * Usage()
  1630.  *
  1631.  * Print usage & syntax message.
  1632. \*----------------------------------------------------------------------*/
  1633.  
  1634. static void
  1635. Usage(char *badOption)
  1636. {
  1637.     dbug_enter("Usage");
  1638.  
  1639.     if (*badOption != '\0')
  1640.     fprintf(stderr, "\n%s:  bad command line option \"%s\"\r\n",
  1641.         program_name, badOption);
  1642.  
  1643.     fprintf(stderr,
  1644.         "\nUsage:\n        %s [%s options] [plplot options] [filename]\n",
  1645.         program_name, program_name);
  1646.  
  1647.     if (mode_showall)
  1648.     mode_plplot |= PL_PARSE_SHOWALL;
  1649.  
  1650.     mySyntax();
  1651.     plSyntax(mode_plplot);
  1652.  
  1653.     fprintf(stderr, "\nType %s -h for a full description.\r\n\n",
  1654.         program_name);
  1655.  
  1656.     exit(1);
  1657. }
  1658.  
  1659. /*----------------------------------------------------------------------*\
  1660.  * mySyntax()
  1661.  *
  1662.  * Print syntax message appropriate for plrender options only.
  1663. \*----------------------------------------------------------------------*/
  1664.  
  1665. static void
  1666. mySyntax(void)
  1667. {
  1668.     PLOptionTable *tab;
  1669.     int col, len;
  1670.  
  1671.     fprintf(stderr, "\n%s options:", program_name);
  1672.  
  1673.     col = 80;
  1674.     for (tab = option_table; tab->opt; tab++) {
  1675.     if ( ! (tab->mode & PL_OPT_ENABLED))
  1676.         continue;
  1677.  
  1678.     if ( ! mode_showall && (tab->mode & PL_OPT_INVISIBLE))
  1679.         continue;
  1680.  
  1681.     if (tab->syntax == NULL)
  1682.         continue;
  1683.  
  1684.     len = 3 + strlen(tab->syntax);        /* space [ string ] */
  1685.     if (col + len > 79) {
  1686.         fprintf(stderr, "\r\n   ");        /* 3 spaces */
  1687.         col = 3;
  1688.     }
  1689.     fprintf(stderr, " [%s]", tab->syntax);
  1690.     col += len;
  1691.     }
  1692.     fprintf(stderr, "\r\n");
  1693. }
  1694.  
  1695. /*----------------------------------------------------------------------*\
  1696.  * Input handlers
  1697. \*----------------------------------------------------------------------*/
  1698.  
  1699. /*----------------------------------------------------------------------*\
  1700.  * Opt_h()
  1701.  *
  1702.  * Performs appropriate action for option "h".
  1703. \*----------------------------------------------------------------------*/
  1704.  
  1705. static int
  1706. Opt_h(char *opt, char *optarg, void *client_data)
  1707. {
  1708. /* Help */
  1709.  
  1710.     Help();
  1711.  
  1712.     return 1;
  1713. }
  1714.  
  1715. /*----------------------------------------------------------------------*\
  1716.  * Opt_v()
  1717.  *
  1718.  * Performs appropriate action for option "v".
  1719. \*----------------------------------------------------------------------*/
  1720.  
  1721. static int
  1722. Opt_v(char *opt, char *optarg, void *client_data)
  1723. {
  1724. /* Version */
  1725.  
  1726.     fprintf(stderr, "plplot metafile version: %s\n", PLMETA_VERSION);
  1727.     fprintf(stderr, "plplot library version: %s\n", PLPLOT_VERSION);
  1728.     exit(1);
  1729.     return 1;        /* This serves a purpose */
  1730. }
  1731.  
  1732. /*----------------------------------------------------------------------*\
  1733.  * Opt_i()
  1734.  *
  1735.  * Performs appropriate action for option "i".
  1736. \*----------------------------------------------------------------------*/
  1737.  
  1738. static int
  1739. Opt_i(char *opt, char *optarg, void *client_data)
  1740. {
  1741. /* Input file */
  1742.  
  1743.     strncpy(FileName, optarg, sizeof(FileName) - 1);
  1744.     FileName[sizeof(FileName) - 1] = '\0';
  1745.  
  1746.     return 0;
  1747. }
  1748.  
  1749. /*----------------------------------------------------------------------*\
  1750.  * Opt_b()
  1751.  *
  1752.  * Performs appropriate action for option "b".
  1753. \*----------------------------------------------------------------------*/
  1754.  
  1755. static int
  1756. Opt_b(char *opt, char *optarg, void *client_data)
  1757. {
  1758. /* Beginning page */
  1759.  
  1760.     if (*optarg == '-') {
  1761.     optarg++;
  1762.     addeof_beg = 1;
  1763.     }
  1764.     disp_beg = atoi(optarg);
  1765.  
  1766.     return 0;
  1767. }
  1768.  
  1769. /*----------------------------------------------------------------------*\
  1770.  * Opt_e()
  1771.  *
  1772.  * Performs appropriate action for option "e".
  1773. \*----------------------------------------------------------------------*/
  1774.  
  1775. static int
  1776. Opt_e(char *opt, char *optarg, void *client_data)
  1777. {
  1778. /* Ending page */
  1779.  
  1780.     if (*optarg == '-') {
  1781.     optarg++;
  1782.     addeof_end = 1;
  1783.     }
  1784.     disp_end = atoi(optarg);
  1785.  
  1786.     return 0;
  1787. }
  1788.  
  1789. /*----------------------------------------------------------------------*\
  1790.  * Opt_p()
  1791.  *
  1792.  * Performs appropriate action for option "p".
  1793. \*----------------------------------------------------------------------*/
  1794.  
  1795. static int
  1796. Opt_p(char *opt, char *optarg, void *client_data)
  1797. {
  1798. /* Specified page only */
  1799.  
  1800.     if (*optarg == '-') {
  1801.     optarg++;
  1802.     addeof_beg = 1;
  1803.     addeof_end = 1;
  1804.     }
  1805.     disp_beg = atoi(optarg);
  1806.     disp_end = disp_beg;
  1807.  
  1808.     return 0;
  1809. }
  1810.